# coding=utf8
# 全世界最帅的帅哥
from flask_restful import Resource, reqparse
from comment.utils.decorators import login_required, root_login_required
from flask import g, current_app, request
from comment.modules.user import User
from comment.utils.financial_redis import fr
from comment.modules.loan_apply import Loan
from .const import LoanConfig
from comment.modules import db
from .serializer import LoanPaginateSerializer
from comment.modules.debt_info import DebtInfo
from comment.utils.gen_trans_id import generate_trans_id
from dateutil.relativedelta import relativedelta
from datetime import datetime
from comment.modules.debt_repay import DebtorRepay


class LoanApply(Resource):
    # 借款的资源类
    method_decorators = {
        "get": [root_login_required],
        "post": [login_required],
        "put": [root_login_required]
    }

    def get(self):
        # 管理员看到的借款列表
        rp = reqparse.RequestParser()
        rp.add_argument("start")
        rp.add_argument("end")
        rp.add_argument("curPage")
        rp.add_argument("perPage")
        rp.add_argument("approveStatus")

        args = rp.parse_args()
        start = args.start
        end = args.end
        cur_page = int(args.curPage)
        per_page = int(args.perPage)
        approve_status = int(args.approveStatus)

        # 过滤查询
        # 1.审批状态
        loan_query = Loan.query.filter(Loan.status == approve_status)
        # 2.时间
        if start:
            loan_query = loan_query.filter(db.cast(Loan.loanStartDate, db.DATE) <= db.cast(start, db.DATE))
        if end:
            loan_query = loan_query.filter(db.cast(Loan.loanStartDate, db.DATE) <= db.cast(end, db.DATE))
        loan_paginate = loan_query.paginate(page=cur_page, per_page=per_page, error_out=False)
        loan_data = LoanPaginateSerializer(loan_paginate).to_dict()
        return {"msg": "查询借款状态成功", "data": loan_data}

    def post(self):
        # 申请借款
        rp = reqparse.RequestParser()
        rp.add_argument("amount", required=True)  # 金额
        rp.add_argument("code", required=True)  # 验证码
        rp.add_argument("loanMonth", required=True)  # 借款期数

        args = rp.parse_args()
        amount = args.amount
        code = args.code
        loan_month = args.loanMonth

        user_id = g.user_id
        user = User.query.filter(User.id == user_id).first()
        try:
            # 验证传入的验证码是否正确
            real_code = fr.get(f"register:{user.phone}")
            # redis中不存在验证码，说明验证码已经过期了
            if not real_code:
                current_app.logger.info("验证码过期！")
                return {"message": "验证码过期了", "code": 20001}
            real_code = real_code.decode("utf8")
            # 填写的验证码与redis中的不匹配，说明输入错误
            if real_code != code:
                current_app.logger.info("验证码错误，请重新输入")
                return {"message": "验证码错误，请重新输入！"}
        except ConnectionError as e:
            current_app.logger.error(e)
            return {"message": "验证码判断的时候，数据库连接错误", "code": "20002"}

        loan_apply = Loan(loanAmount=amount, lUid=user_id, duration=loan_month, lName=user.realName,
                          lRate=LoanConfig.YEAR_RATE.value, applyDate=datetime.now())
        db.session.add(loan_apply)
        db.session.commit()
        return {"msg": "申请借款成功"}

    def put(self):
        """审批借款状态"""
        # 修改借款状态，产出债券，创建还款计划
        rp = reqparse.RequestParser()
        rp.add_argument("applyId")  # 借款申请ID
        rp.add_argument("status")  # 借款审批状态
        args = rp.parse_args()
        loan_id = args.applyId
        status = args.status
        # 查询Loan对象
        loan = Loan.query.filter(Loan.id == loan_id).first()
        if loan.status == 1:
            return {"message": "该笔借款已经审核通过请勿重复审核", "code": 20003}
        # 借款人
        user_id = loan.lUid

        if status == "1":  # 1 代表审批通过
            # 第一步：产生债券对象
            debt_no = generate_trans_id("debt")
            user_id_num = loan.user.idNum  # 身份证号码
            if not user_id_num:
                return {"message": "请先实名认证后再申请借款", "code": 20001}
            # 还款的最后时间
            end_time = datetime.now() + relativedelta(months=loan.duration)
            # 创建债券
            new_debt = DebtInfo(debtNo=debt_no, debtorsName=loan.lName, loanNo=loan.id, borrowerId=user_id,
                                debtorsId=user_id_num, loanStartDate=datetime.now(), loanPeriod=loan.duration,
                                loanEndDate=end_time, repaymentStyle=loan.lRepayType, matchedMoney=0,
                                repaymentDate=loan.lRepayDay, repaymentMoney=loan.loanAmount, matchedStatus=0,
                                debtMoney=loan.loanAmount, debtYearRate=loan.lRate, debtTransferredMoney=0)
            db.session.add(new_debt)
            db.session.flush()
            # 创建还款计划
            self.create_repay_plan(new_debt)

            # 修改借款状态
            loan.status = int(status)
            db.session.commit()
            return {"msg": "审批借款成功"}

    def create_repay_plan(self, new_debt):
        # 创建当前债券的还款计划

        # 月还款本金 = 借款金额 / 借款的期数
        mount_cost = round(float(new_debt.repaymentMoney) / new_debt.loanPeriod, 2)
        # 月利息
        mount_rate = round(LoanConfig.YEAR_RATE.value / 12, 4)

        for month in range(new_debt.loanPeriod):
            # 每一期应还的利息  =  剩下的本金 * 月利息
            interest = round((float(new_debt.repaymentMoney) - (mount_cost * month)) * mount_rate, 2)
            # 每一期应还的总金额  =  每月本金 + 每月利息
            total = mount_cost + interest
            # 创建每一期的还款计划对象

            repay_plan = DebtorRepay(claimsId=new_debt.id, receivableMoney=total, currentTerm=month + 1,
                                     recordDate=datetime.now())
            db.session.add(repay_plan)


class MyLoanApply(Resource):
    # 普通用户查看借款列表
    method_decorators = [login_required]

    def get(self):
        rp = reqparse.RequestParser()
        rp.add_argument("curPage")
        rp.add_argument("perPage")

        args = rp.parse_args()
        cur_page = args.curPage
        per_page = args.perPage

        user_id = g.user_id
        data = Loan.query.filter(Loan.lUid == user_id).paginate(page=cur_page, per_page=per_page, error_out=False)
        return {"msg": "查询借款状态成功", "data": data}
